package com.shuaigexue.exam.service.impl;



import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuaigexue.exam.entity.Category;
import com.shuaigexue.exam.entity.Question;
import com.shuaigexue.exam.mapper.CategoryMapper;
import com.shuaigexue.exam.mapper.QuestionMapper;
import com.shuaigexue.exam.service.CategoryService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {


    @Resource
    private QuestionMapper questionMapper;

    /**
     * 查询所有分类
     * @return 分类集合
     */
    @Override
    public List<Category> findCategoryList() {
        // 1. 查询所有的分类信息集合(单表操作) -> mybatis-plus 提供的list方法即可
        // List<Category> 每个分类对象没有count
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Category::getSort); // sort 正序排序查询
        List<Category> categoryList = this.list(wrapper);

        // 2. QuestionMapper 定义查询方法， category_id 进行分组，并且统计每个分类下的count
        List<Map<String, Long>> mapList = questionMapper.selectCategoryQuestionCount();
        // 3. 题目查询的分类的题目数量复值给分类集合
        // 这里进行stream流，将里面的数据categoryId作为key ，count作为value放到map中
        Map<Long, Long> countMap = mapList.stream().collect(Collectors.toMap(m -> m.get("category_id"), m -> m.get("count")));
        for (Category category : categoryList) {
            Long id = category.getId();
            category.setCount(countMap.getOrDefault(id, 0L));
        }


        // 4. 返回对应的查询集合即可
        return categoryList;
    }

    @Override
    public List<Category> findCategoryListTree() {
        // 1. 查询所有的分类信息集合(单表操作) -> mybatis-plus 提供的list方法即可
        // List<Category> 每个分类对象没有count
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Category::getSort); // sort 正序排序查询
        List<Category> categoryList = this.list(wrapper);

        // 2. QuestionMapper 定义查询方法， category_id 进行分组，并且统计每个分类下的count
        List<Map<String, Long>> mapList = questionMapper.selectCategoryQuestionCount();
        // 3. 题目查询的分类的题目数量复值给分类集合
        // 这里进行stream流，将里面的数据categoryId作为key ，count作为value放到map中
        Map<Long, Long> countMap = mapList.stream().collect(Collectors.toMap(m -> m.get("category_id"), m -> m.get("count")));
        for (Category category : categoryList) {
            Long id = category.getId();
            category.setCount(countMap.getOrDefault(id, 0L));
        }
        // 4. 分类信息进行分组，以parent_id分组
        // key: parent_id value: List<Category>子分类
        Map<Long, List<Category>> longListMap = categoryList.stream().collect(Collectors.groupingBy(Category::getParentId));

        // 5. 筛选分类信息(获取到一级分类后，进行循环将子分类塞进去)
        // 获取一级分类
        List<Category> parentCategoryList = categoryList.stream().filter(c -> c.getParentId() == 0).collect(Collectors.toList());

        // 6. 循环一级分类，将子分类塞进去，并计算count(父分类的count+所有子分类的count)
        for (Category category : parentCategoryList) {
            // 获取一级分类下的子分类
            List<Category> childCategory = longListMap.getOrDefault(category.getId(),new ArrayList<>());
            category.setChildren(childCategory);
            Long sonCollect = childCategory.stream().collect(Collectors.summingLong(Category::getCount));
            category.setCount(category.getCount() + sonCollect);
        }
        return parentCategoryList;
    }

    @Override
    public void saveCategory(Category category) {
        // 1. 当前父分类下不能存在同名的子分类
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getParentId, category.getParentId()).eq(Category::getName, category.getName());
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("%s父分类下,已存在 %s子分类,添加失败".formatted(category.getParentId(), category.getName()));
        }
        save(category);
    }

    @Override
    public void updateCategory(Category category) {
        // 1. 条件校验工作(同一个父分类下，不能于其他子分类name相同，可以和自己原来的name相同)
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getParentId, category.getParentId())
                .eq(Category::getName, category.getName())
                .ne(Category::getId, category.getId());
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("%s父分类下,已存在 %s子分类,本次更新失败".formatted(category.getParentId(), category.getName()));
        }
        // 2. 数据分类的更新
        this.updateById( category);
    }

    @Override
    public void removeCategory(Long id) {
        // 1. 先判定是不是一级分类
        Category category = this.getById(id);
        if(category == null){
            log.debug("要删除的分类不存在：{}", id);
            return ;
        }
        if(category.getParentId() == 0){
            throw new RuntimeException("id = %s 的分类为一级分类，请勿删除一级分类".formatted( id));
        }
        // 2. 判定有没有关联的题目

        LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        questionLambdaQueryWrapper.eq(Question::getCategoryId,id);
        if(questionMapper.selectCount(questionLambdaQueryWrapper) > 0){
            throw new RuntimeException("id = %s 的分类下有题目，请先删除题目".formatted(id));
        }

        // 3. 才可以进行删除分类
        removeById(id);
    }
}